package parallel.project.solver;

import java.io.IOException;

import parallel.project.framework.Mazemap;
import parallel.project.graph.Graph;
import parallel.project.graph.GraphFactory;
import parallel.project.graph.Node;
import parallel.project.graph.Path;

/**
 * Main class for running the project.
 * 
 * @author Adam Clayton
 * @author Larry Walters
 */
public class Solver {

	/**
	 * Program takes three arguments:
	 * <li>Input file: serialized version of a maze
	 * <li>Output file: serialized path from start to end
	 * <li>Number of solving threads (note there will be one more for
	 * the main thread)
	 * <br>
	 * 
	 * @param args
	 * 		Command line arguments
	 */
	public static void main(String[] args)
	{
		if (args.length != 3)
		{
			System.out.println("Usage: inputfile outputfile numthreads");
			System.exit(0);
		}
		// extract the input and output filenames, and number of threads
		String inputFile = args[0];
		String outputFile = args[1];
		int threads = 1;
		try {threads = Integer.parseInt(args[2]);}
		catch (NumberFormatException nfe)
		{
			System.out.println("Number of threads must be an integer");
			System.exit(1);
		}
		
		// the start time
		long startTime = System.currentTimeMillis();
		// create the graph from the maze with the given number of 
		// threads
		Graph graph = null;
		GraphFactory graphMaker = new GraphFactory();
		try {graph = graphMaker.makeMazemapGraph(inputFile,threads);} 
		catch (Exception e)
		{
			System.out.println("Error occured in graph creation:");
			System.out.println(e.getMessage());
			System.exit(1);
		}
		Mazemap maze = graphMaker.getLastMaze();
		
		// run A* on the graph to get the path from the start to the end
		// nodes
		Node start = graph.getAllStartNodes().get(0);
		Node goal = graph.getAllEndNodes().get(0);
		Path path = graph.solveAStar(start,goal);
		// so everything is in the right order
		path.orderLocations();
		// set the end time
		long endTime = System.currentTimeMillis();
		// output the path and graph
		try 
		{
			// print out the path, both serialized and text
			path.writePath(outputFile);
//			path.printPath();
			// serialize the graph
			graph.writeGraph(outputFile + ".graph");
			// also write the graph to dot format with the path
			graph.toDot(outputFile + ".dot",path);
//			// finally, print the maze with the path in text form
//			maze.printMazemap(path);
		}
		catch (IOException ioe) {ioe.printStackTrace();}
		System.out.println("InputFile: " + inputFile + " OutputFile: " +
			outputFile + " #threads: " + threads);
		// get the difference in time
		System.out.println("Elapsed Time : " + 
			calcTime(startTime,endTime) + "s");
		
		System.out.println("Finished!");
	}

	/**
	 * Returns the elapsed time between the two given millisecond times.
	 * Returned time is in seconds.
	 * 
	 * @param start
	 * 		Start time
	 * @param end
	 * 		End time
	 * 
	 * @return
	 * 		Difference in time in seconds
	 */
	public static double calcTime(long start, long end)
	{
		return ((double)(end - start)) / Math.pow(10,3);
	}
}
